package com.loan.common.pay.oddpay;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.loan.common.utils.MD5;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 虚拟卡工具类
 *
 * @author shiguang on 2022/9/14 16:21
 */
@Slf4j
public class VaUtils {

    public static String md5Key = "8BB418FCA8A480BC3E00365AE14148A2";
    //public static String md5Key = "8E033403B733D0AADD5F359E";
    public static String PAY_URL = "https://pay.vnoddpay.com:8090/pay-adapter/services/va/reg";

    private static String URL = "https://pay.vnoddpay.com:8090/pay-adapter/services/payment/paymentReq";

    private static String TEXT_URL = "http://161.117.196.84:8090/pay-adapter/services/payment/paymentReq";

    private static String ORDER_QUERY_URL = "https://pay.vnoddpay.com:8090/pay-adapter/services/order/singleQuery";

    private static String PMT_PRODCODE = "mgp_disbirsement";

    private static String MD5_KEY = "8BB418FCA8A480BC3E00365AE14148A2";

    private static String MERCHANT_ID = "m1907130001";
    private static String APP_ID = "30kFqjinwGiIZfE8ZSa01g";

    private static String CHANNEL = "MEGAPAY";

    /**
     * 创建虚拟卡
     */
    public static Map<String, Object> createVa(String merchantId, String appId, String mapId,String amount, String startDate, String endDate,
                                               String customerName, String notifyUrl) {
        /**
         * 渠道号
         */
        String pmtProdCode = "mgp_va";
        //mapId 测试时此值需要修改，此值是唯一的，m1907130001202007256788912已被使用
//        String mapId = UUID.randomUUID().toString();

        /**
         * 无条件
         */
        String condition = "01";

        /**
         * 固定值
         */
        String bankCode = "WOORIBANK";

        log.info(merchantId + appId + pmtProdCode + mapId + md5Key);
        /**
         * 签名
         */
        String sign = MD5.sign(merchantId + appId + pmtProdCode + mapId, md5Key, "UTF-8");
        System.out.println(sign);
        HashMap<String, String> map1 = new HashMap<String, String>();
        map1.put("merchantId", merchantId);
        map1.put("appId", appId);
        map1.put("pmtProdCode", pmtProdCode);
        map1.put("mapId", mapId);
        map1.put("amount", amount);
        map1.put("startDate", startDate);
        map1.put("endDate", endDate);
        map1.put("condition", condition);
        map1.put("customerName", customerName);
        map1.put("bankCode", bankCode);
        map1.put("notifyUrl", notifyUrl);
        map1.put("sign", sign);
        Map<String, Object> resmap1 = HttpClientUtil.httpSendPost(PAY_URL, map1);
        return resmap1;
//        System.out.println(net.sf.json.JSONObject.fromObject(resmap1));
    }


    /**
     *
     * @param merchantId
     * @param appId
     * @param amount
     * @param orderId
     * @param cpAccountNo  银行卡号
     * @param cpAccountName  银行卡持有人
     * @param bankNo  银行卡code
     * @param bankName 银行简称
     * @param remark  备注
     * @param notifyUrl  回调地址
     * @return
     */
    public static Map<String, Object> payreq(String merchantId, String appId, String amount, String orderId,
                                             String cpAccountNo, String cpAccountName, String bankNo,
                                             String bankName, String remark, String notifyUrl) {
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("merchantId", merchantId);
        map.put("pmtProdCode", PMT_PRODCODE);
        map.put("appId", appId);

        //此字段需是唯一
        map.put("cpOrderId", orderId);
        //卡号为错误卡号，需要用户换为自己的有效卡号
        map.put("cpAccountNo", cpAccountNo);
        map.put("cpAccountName", cpAccountName);
        map.put("bankNo", bankNo);
        map.put("cpAccountType", "0");
        map.put("bankName", bankName);
        map.put("amount", amount);
        map.put("remark", remark);
        //notifyurl 需要http开头，为三方预留，可填非真实地址
        map.put("notifyUrl", notifyUrl);

        String sign = merchantId + appId + PMT_PRODCODE + amount;
        sign = MD5.sign(sign, MD5_KEY, "utf-8");
        map.put("sign", sign);
        log.info(sign);
        Map<String, Object> resmap1 = HttpClientUtil.httpSendPost(TEXT_URL, map);
        System.out.println(resmap1.get(""));
        System.out.println("代付返回" + net.sf.json.JSONObject.fromObject(resmap1));
        return resmap1;
//
    }

    /**
     * 订单查询
     *
     * @param appId  appId
     * @param order_no
     */
    public static String queryOrderMd5(String appId, String order_no) {
        // 1. 查询参数设置
        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("app_id", appId);
        hashMap.put("charset", "UTF-8");
        hashMap.put("order_no", order_no);
        hashMap.put("channel", CHANNEL);
        hashMap.put("version", "V2.0.0");
        hashMap.put("sign_type", "MD5");

        Map<String, ?> paraFilter = paraFilter(hashMap);
        String content = createLinkString(paraFilter);
        log.info("请求参数:" + content);
        String templinkStr = content + "&key=" + MD5_KEY;
        log.info("完整串：" + templinkStr);
        String sign_info = "";
        try {
            sign_info = DigestUtils.md5Hex(templinkStr.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.info("处理时出现异常,e:" + e);
        }
        log.info("签名信息:" + sign_info);
        hashMap.put("sign_info", sign_info);

        // 2. 订单查询
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setExpires(1000 * 5);
        HttpEntity<String> entity = new HttpEntity<String>(JSON.toJSONString(hashMap), headers);
        ResponseEntity<String> response = restTemplate.postForEntity(ORDER_QUERY_URL, entity, String.class);
        System.out.println("查询订单结果:" + response.getBody());
        return response.getBody();
    }

    /**
     * 除去数组中的空值和签名参数
     *
     * @param sArray 签名参数组
     * @return 去掉空值与签名参数后的新签名参数组
     */
    private static Map<String, ?> paraFilter(Map<String, ?> sArray) {
        Map<String, Object> result = new HashMap<String, Object>();
        if ((sArray == null) || (sArray.size() <= 0)) {
            return result;
        }
        for (String key : sArray.keySet()) {
            Object value = sArray.get(key);
            if ((value == null) || value.equals("")
                    || key.equalsIgnoreCase("sign_info")
                    || key.equalsIgnoreCase("signInfo")
                    || key.equalsIgnoreCase("sign_type")) {
                continue;
            }
            if (value instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, ?> m = (Map<String, ?>) value;
                result.put(key, paraFilter(m));
            } else if (value instanceof List) {
                continue;// 不应包含多集合数据
            } else {
                result.put(key, value);
            }
        }
        return result;
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, ?> params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);

        StringBuffer prestr = new StringBuffer("");
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            Object o = params.get(key);
            String value = String.valueOf(o);
            if (o instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, ?> m = (Map<String, ?>) o;
                value = "{" + createLinkString(m) + "}";
            }

            if (i == (keys.size() - 1)) {// 拼接时，不包括最后一个字符
                prestr.append(key + "=" + value);
            } else {
                prestr.append(key + "=" + value + "&");
            }
        }
        return prestr.toString();
    }


    public static void main(String[] args) {
//        createVa();
//        payreq(null,null);
//        queryOrderMd5(APP_ID, "local1663748576082", "MEGAPAY");
    }

}
